package com.zyzo.demo.appengine.client.customwidget.user;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Set;

import org.restlet.client.Request;
import org.restlet.client.Response;
import org.restlet.client.Uniform;
import org.restlet.client.data.ChallengeScheme;
import org.restlet.client.data.MediaType;
import org.restlet.client.ext.json.JsonRepresentation;
import org.restlet.client.resource.ClientResource;

import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.AsyncHandler;
import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.Range;
import com.google.gwt.view.client.SelectionModel;
import com.zyzo.demo.appengine.client.Json2Model.Converter;
import com.zyzo.demo.appengine.model.ServerReponse;
import com.zyzo.demo.appengine.model.User;

public class CustomerCellTable extends Composite
{
	private static CustomerCellTableUiBinder uiBinder = GWT.create(CustomerCellTableUiBinder.class);

	interface CustomerCellTableUiBinder extends UiBinder<Widget, CustomerCellTable> 
	{
	}

	
	/**
	 * The main CellTable.
	 */
	@UiField(provided = true) CellTable<User> cellTable;

	/**
	 * The pager used to change the range of data.
	 */
	@UiField(provided = true) SimplePager pager;
	
	/**
	 * Insert & delete buttons
	 */
	@UiField Button insertButton;
	@UiField Button deleteButton;

	  
    /**
     * The key provider that provides the unique ID of a contact.
     */
    public static final ProvidesKey<User> KEY_PROVIDER = new ProvidesKey<User>() {
      public Object getKey(User item) {
        return item == null ? null : item.getId();
      }
    };
    
    /**
     * Hashamp to bind column and sort names
     */
    private HashMap< Column , String> columnSortArgs = new  HashMap< Column , String>();
    
    
    /**
     * MultiSelectionModel , to select users from the table
     */
    private MultiSelectionModel<User> multiSelectionModel = new MultiSelectionModel<User>( CustomerCellTable.KEY_PROVIDER ); 
    
    /**
     * The provider that holds the list of contacts in the database.
     */
    private AsyncDataProvider<User> dataProvider =  new AsyncDataProvider<User>() 
    {
    	
        @Override
        protected void onRangeChanged(HasData<User> display) 
        {
        	 // Get the new range.
        	final Range range = display.getVisibleRange();
        	final int start = range.getStart();
        	final int length = range.getLength();
      	
        	// Get the ColumnSortInfo from the table.
        	ColumnSortInfo csi = cellTable.getColumnSortList().get(0) ;
        	String sortCriteria = columnSortArgs.get( csi.getColumn() ) ;
            boolean ascending = csi.isAscending();
        	
    		ClientResource r = new ClientResource("/rest/admin/user?sort="+sortCriteria+"&asc="+ascending+"&start="+start+"&length="+length);
    		r.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin@mail.com", "admin");
    		r.setOnResponse
    		(
    			new Uniform() 
    			{
    				public void handle(Request request, Response response) 
    				{
   			        ArrayList<User> newData = new ArrayList<User>();
    			          
    		        	// Get the representation as an JsonRepresentation
    		        	JsonRepresentation rep = new JsonRepresentation(response.getEntity());

    		        	// Displays the properties and values.
    		        	try {
    		        		JSONArray array = rep.getValue().isArray();
    		        		for( int i = 0 ; i< Math.min( array.size() , length )  ; i++ )
    		        		{
    		        			JSONObject object = array.get(i).isObject() ;
    		        			if (object != null) 
    		        			{
    		        				User u = Converter.getInstance().jsonToUser( object) ; 
    		        				newData.add( u );
    		        			}
    		        		}
    		        		
    		        	} catch (IOException e) {
    		        		e.printStackTrace();
    		        	}
    		        	
     			      // Push the data to the displays. AsyncDataProvider will only update
  			          // displays that are within range of the data.
  			          updateRowData(start, newData);

    		        	
    				}
    			}
    		);
    		r.get();          
        }
        
        
        
      };
    
    
	public CustomerCellTable() 
	{
		
		this.init();
		
		initWidget(uiBinder.createAndBindUi(this));
		
	}

	
	
	
	private void  init() 
	{
		
		// Create a CellTable.

		// Set a key provider that provides a unique key for each contact. If key is
		// used to identify contacts when fields (such as the name and address)
		// change.
		cellTable = new CellTable<User>( CustomerCellTable.KEY_PROVIDER);
		cellTable.setWidth("100%", true);
		cellTable.setTableLayoutFixed(false);

	    // Add a ColumnSortEvent.AsyncHandler to connect sorting to the
	    // AsyncDataPRrovider.
	    AsyncHandler columnSortHandler = new AsyncHandler(cellTable);
	    cellTable.addColumnSortHandler(columnSortHandler);

		// Create a Pager to control the table.
		SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
		pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true);
		pager.setDisplay(cellTable);
		
	    
		// Set the range to display. In this case, our visible range is smaller than
	    // the data set.
		cellTable.setVisibleRange(0,10);

		// Add a selection model so we can select cells.
		//final SelectionModel<User> selectionModel = new MultiSelectionModel<User>( CustomerCellTable.KEY_PROVIDER );
		cellTable.setSelectionModel( multiSelectionModel , DefaultSelectionEventManager.<User> createCheckboxManager());

		// Initialize the columns.
		initTableColumns( multiSelectionModel , columnSortHandler);
		
		// Add the CellList to the adapter in the database.
		dataProvider.addDataDisplay(cellTable);
		
	    // Set the total row count. You might send an RPC request to determine the
	    // total row count.
		this.countUsers();

	}
	
	private void countUsers()
	{
		ClientResource cr = new ClientResource("/rest/admin/userutils/1");
		cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin@mail.com", "admin");
		cr.setOnResponse
		(
			new Uniform() 
			{
		        public void handle(Request request, Response response) 
		        {
		        	try 
		        	{
		        		JsonRepresentation rep = new JsonRepresentation(response.getEntity());
		        		
		        		JSONObject object = rep.getJsonObject() ;
	        			if (object != null) 
	        			{
	        				ServerReponse u = Converter.getInstance().jsonToServerReponse( object) ; 
	        				
	        				int count = Integer.parseInt(  u.getMessage().replaceAll("\"", "")  );
	        				//cellTable.setRowCount(count,true);
	        				dataProvider.updateRowCount( count , true);
	        			}
	        			
					} catch (IOException e) {
						Window.alert(e.getMessage());
					}
		        }
			}
		);
		
		cr.get() ;    		
	}
	
	  /**
	   * Add the columns to the table.
	   */
	private void initTableColumns(final SelectionModel<User> selectionModel, AsyncHandler sortHandler) 
	{
		
		// Checkbox column. This table will uses a checkbox column for selection.
		// Alternatively, you can call cellTable.setSelectionEnabled(true) to enable
		// mouse selection.
		Column<User, Boolean> checkColumn = new Column<User, Boolean>( new CheckboxCell(true, false)) {
			@Override
			public Boolean getValue(User object) {
				// Get the value from the selection model.
				return selectionModel.isSelected(object);
			}
		};
		cellTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("<br/>"));
		cellTable.setColumnWidth(checkColumn, 40, Unit.PX);

		// First name.
		Column<User, String> firstNameColumn = new Column<User, String>(
				new EditTextCell()) {
			@Override
			public String getValue(User object) 
			{
				return object.getFirstname();
			}
		};
		firstNameColumn.setSortable(true);columnSortArgs.put(  firstNameColumn   , "firstname");
		
		cellTable.addColumn(firstNameColumn, "PREN" );
		firstNameColumn.setFieldUpdater(new FieldUpdater<User, String>() 
		{
			public void update(int index, User object, String value) {
				// Called when the user changes the value.
				object.setFirstname(value);
				updateUser( index, object);
			}
		});
		cellTable.setColumnWidth(firstNameColumn, 20, Unit.PCT);

		// Last name.
		Column<User, String> lastNameColumn = new Column<User, String>(
				new EditTextCell()) {
			@Override
			public String getValue(User object) {
				return object.getLastname();
			}
		};
		lastNameColumn.setSortable(true);columnSortArgs.put( lastNameColumn , "lastname");
		
		cellTable.addColumn(lastNameColumn, "NOM" );
		lastNameColumn.setFieldUpdater(new FieldUpdater<User, String>() {
			public void update(int index, User object, String value) {
				// Called when the user changes the value.
				object.setLastname(value);
				updateUser( index, object);
			}
		});
		cellTable.setColumnWidth(lastNameColumn, 20, Unit.PCT);

		
		// eMail.
		Column<User, String> addressColumn = new Column<User, String>( new TextCell() ) 
			{
			@Override
			public String getValue(User object) {
				return object.getEmail();
			}
		};
		addressColumn.setSortable(true);columnSortArgs.put( addressColumn  , "email");
		
		cellTable.addColumn(addressColumn, "ADR" );
		cellTable.setColumnWidth(addressColumn, 60, Unit.PCT);
		
		
		
		// subscriptionDate
		Column<User, Date> subscriptionDateColumn = new Column<User, Date>( new DateCell( DateTimeFormat.getFormat("dd/MM/yyyy ',' HH:mm")   )  ) 
			{
			@Override
			public Date getValue(User object) {
				return (   object.getSubscriptionDate() );
			}
		};
		subscriptionDateColumn.setSortable(true);columnSortArgs.put( subscriptionDateColumn  , "subscriptionDate");
		
		cellTable.addColumn(subscriptionDateColumn, "DATE" );
		cellTable.setColumnWidth(subscriptionDateColumn, 60, Unit.PCT);

		
	    // Add a ColumnSortEvent.AsyncHandler to connect sorting to the
	    // AsyncDataPRrovider.
	    AsyncHandler columnSortHandler = new AsyncHandler(cellTable);
	    cellTable.addColumnSortHandler(columnSortHandler);

	    // We know that the data is sorted alphabetically by default.
	    cellTable.getColumnSortList().push( firstNameColumn  );
	}
	
	
	@UiHandler("insertButton")
	void onInsertButtonClick(ClickEvent event) 
	{
		User userPost = new User();
		long r = (new Date()).getTime() ;
		
		userPost.setId( r );
		userPost.setEmail( "mail"+r );
		userPost.setFirstname("firstname"+r);
		userPost.setLastname("lastname"+r);
		userPost.setPassword("password"+r);
		userPost.setPhone("phone"+r);
		userPost.setSubscriptionDate( new Date() );
		
		ClientResource cr = new ClientResource("/rest/admin/user");
		cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin@mail.com", "admin");
		cr.setOnResponse
		(
			new Uniform() 
			{
		        public void handle(Request request, Response response) 
		        {
		        	try 
		        	{
						Window.alert( response.getEntity().getText() );
						
						cellTable.setVisibleRangeAndClearData( cellTable.getVisibleRange() , true );
						
					} catch (IOException e) {
						Window.alert(e.getMessage());
					}
		        }
			}
		);
		
		JSONObject jsonvalue =  Converter.getInstance().userToJson(userPost) ;
		cr.put( new JsonRepresentation( MediaType.APPLICATION_JSON, jsonvalue ) );    		
	}
	
	
	
	@UiHandler("deleteButton")
	void onDeleteButtonClick(ClickEvent event) 
	{
		Window.alert( "deleteButton" );
		Set< User > s = multiSelectionModel.getSelectedSet();
		
		for (User user : s) 
		{
			final User userToDelete = user ;
			ClientResource cr = new ClientResource("/rest/admin/user/"+ user.getId() );
			cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin@mail.com", "admin");
			cr.setOnResponse
			(
				new Uniform() 
				{
			        public void handle(Request request, Response response) 
			        {
			        	try 
			        	{
							Window.alert( response.getEntity().getText() );
							
							multiSelectionModel.setSelected( userToDelete , false );
							dataProvider.updateRowCount( cellTable.getRowCount() -1 , true ); 
							
							cellTable.setVisibleRangeAndClearData( cellTable.getVisibleRange() , true );
							
						} catch (IOException e) {
							Window.alert(e.getMessage());
						}
			        }
				}
			);
			
			cr.delete();
		}
	}
	
	
	private void updateUser( final int positionInList , final User userPost )
	{
		
		ClientResource cr = new ClientResource("/rest/admin/user");
		cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, "admin@mail.com", "admin");
		cr.setOnResponse
		(
			new Uniform() 
			{
		        public void handle(Request request, Response response) 
		        {
		        	try 
		        	{
						Window.alert( response.getEntity().getText() );
						
						
						ArrayList<User> l =new ArrayList<User>();l.add( userPost );
						dataProvider.updateRowData(positionInList, l);
						
					} catch (IOException e) {
						Window.alert(e.getMessage());
					}
		        }
			}
		);
		
		JSONObject jsonvalue =  Converter.getInstance().userToJson(userPost) ;
		cr.post( new JsonRepresentation( MediaType.APPLICATION_JSON, jsonvalue ) );  
		

	}
	
	 
	
}
